package util;

import java.io.Serializable;

public class Vector4f extends Tuple4f implements Serializable
{
    /**
	 * 
	 */
	private static final long serialVersionUID = -1036853883459994879L;


	/**
     * Constructs and initializes a Vector4f to (0,0,0,0).
     */

    public Vector4f()
    {
    }


    /**
     * Constructs and initializes a Vector4f from the specified xyzw coordinates.
     * @param x
     * @param y
     * @param z
     * @param w
     */

    public Vector4f(float x, float y, float z, float w)
    {
        super(x, y, z, w);
    }


    /**
     * Constructs and initializes a Vector4f from the array of length 4.
     * @param v
     */

    public Vector4f(float v[])
    {
        super(v);
    }


    /**
     * Constructs and initializes a Vector4f from the specified Vector4f.
     * @param v
     */

    public Vector4f(Vector4f v)
    {
        super(v);
    }


    /**
     *  Constructs and initializes a Vector4f from the specified Tuple4f.
     * @param t
     */

    public Vector4f(Tuple4f t)
    {
        super(t);
    }


    /**
     * Constructs and initializes a Vector4f from the specified Tuple3f.
     * @param t
     */

    public Vector4f(Tuple3f t)
    {
        super(t.x, t.y, t.z, 1.0F);
    }
    
    /**
     * Constructs and initializes a Vector4f from the specified Tuple3f and a 4th component w
     * @param t
     */

    public Vector4f(Tuple3f t, float w)
    {
        super(t.x, t.y, t.z, w);
    }


    /**
     * Sets the x,y,z components of this vector to the corresponding components of tuple t1.
     * @param t
     */

    public final void set(Tuple3f t)
    {
        x = t.x;
        y = t.y;
        z = t.z;
        w = 0.0F;
    }
    
    public Vector3f get3DVector(){
    	return new Vector3f(x,y,z);
    }
    
    /**
     * Adds v to this vector
     * @param v the vector to add to this vector
     * @return w = this + v
     */
    public Vector4f add(Vector3f v){
    	return new Vector4f(this.x + v.x, this.y + v.y, this.z + v.z,this.w);
    }
    
    /**
     * Adds v to this vector
     * @param v the vector to add to this vector
     * @return w = this + v
     */
    public Vector4f add(Vector4f v){
    	return new Vector4f(this.x + v.x, this.y + v.y, this.z + v.z, this.w + v.w);
    }
    
    /**
     * Subtracts v from this vector
     * @param v the vector to subtract from this vector
     * @return w = this - v
     */
    public Vector4f subtract(Vector3f v){
    	return new Vector4f(this.x - v.x, this.y - v.y, this.z - v.z, this.w);
    }
    
    /**
     * Subtracts v from this vector
     * @param v the vector to subtract from this vector
     * @return w = this - v
     */
    public Vector4f subtract(Vector4f v){
    	return new Vector4f(this.x - v.x, this.y - v.y, this.z - v.z, this.w - v.w);
    }
    
    
    /**
     * Scales this vector with a scalar r
     * @param r the scalar to scale this vector by
     * @return w = r * v
     */
    public Vector4f scale(float r){
    	return new Vector4f(this.x * r, this.y * r, this.z * r, this.w);
    }
    
    /**
     * Returns the dot product (scalar product, inner product) of this vector and v (this . v)
     * @param v the vector to take the cross product with
     * @return w = this . v
     */
    public float dot(Vector3f v){
    	return this.x * v.x + this.y * v.y +  this.z * v.z;
    }
    
    /**
     * Returns the length (modulus) of this vector
     * @return |this|
     */
    public float length(){
    	return (float)Math.sqrt(x*x + y*y + z*z);
    }
    
    /**
     * Returns the modulus (length) of this vector
     * @return |this|
     */
    public float modulus(){
    	return length();
    }
    
    /**
     * Returns the normalized vector of this
     * @return this/|this|
     */
    public Vector4f normalize(){
    	return this.scale(1/this.length());
    }
    
    /**
     * Indicates whether this vector is perpendicular to the other one.
     * @return true if the vectors are perpendicular
     */
    public boolean isPerpendicularTo(Vector3f v){
    	return (this.dot(v) <= 0.00000001f && this.dot(v) >= 0f);
    }
    
    public boolean equals(Object other){
    	if(!(other instanceof Vector4f))
    		return false;
    	Vector4f o = (Vector4f)other;
    	return x==o.x && y==o.y && z==o.z && w == o.w;
    }

}
